package com.genius.controller;

import cn.hutool.core.date.DateUtil;
import com.genius.annotation.PreFuncAuth;
import com.genius.core.JSONResult;
import com.genius.utils.PageUtils;
import com.genius.utils.SecurityUtils;
import com.genius.workflow.bo.SelectHighLightActivitiesBO;
import com.genius.workflow.bo.SelectHistoryByIdBO;
import com.genius.workflow.bo.SelectHistoryByPageBO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;

@RestController
@RequestMapping("processHistory")
@Api(value = "流程历史接口", tags = {"用于流程历史的接口"})
public class HistoryController {

    @Autowired
    private HistoryService historyService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ProcessEngine processEngine;

    @PostMapping("/selectHistoryByPage")
    @ApiOperation(value = "查询历史任务（分页查询）",notes = "查询历史任务（分页查询）", httpMethod = "POST")
    @PreFuncAuth("PROCESS:INSTANCE:SELECT")
    public JSONResult selectHistoryByPage(@Valid @RequestBody SelectHistoryByPageBO selectHistoryByPageBO){
        String username = SecurityUtils.getUsername();
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceStartTime().desc()
                .orderByHistoricTaskInstanceEndTime().desc()
                .taskAssignee(username)
                .list();
        List<HashMap<String,Object>> historicTaskList = new ArrayList<>();
        for(HistoricTaskInstance historicTaskInstance:historicTaskInstanceList){
            HashMap<String,Object> historicTask = new HashMap<>();
            historicTask.put("id",historicTaskInstance.getId());
            historicTask.put("taskDefinitionKey",historicTaskInstance.getTaskDefinitionKey());
            historicTask.put("processInstanceId",historicTaskInstance.getProcessInstanceId());
            historicTask.put("processDefinitionId",historicTaskInstance.getProcessDefinitionId());
            historicTask.put("name",historicTaskInstance.getName());
            //获取发起人
            String startUser = historyService.createHistoricProcessInstanceQuery().processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult().getStartUserId();
            historicTask.put("startUser",startUser);
            historicTask.put("assignee",historicTaskInstance.getAssignee());
            historicTask.put("startTime", historicTaskInstance.getCreateTime());
            historicTask.put("endTime",historicTaskInstance.getEndTime());
            historicTaskList.add(historicTask);
        }
        Integer pageNum = selectHistoryByPageBO.getPageNum();
        Integer pageSize = selectHistoryByPageBO.getPageSize();
        Map<String,Object> result = PageUtils.getResultTableData(historicTaskList,pageNum,pageSize);
        return JSONResult.ok(result);
    }

    @PostMapping("/selectHistoryById")
    @ApiOperation(value = "按实例ID查询历史任务",notes = "按实例ID查询历史任务", httpMethod = "POST")
    @PreFuncAuth("PROCESS:INSTANCE:SELECT")
    public JSONResult selectHistoryById(@Valid @RequestBody SelectHistoryByIdBO selectHistoryByIdBO){
        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .orderByHistoricActivityInstanceStartTime().asc()
                .orderByHistoricActivityInstanceEndTime().asc()
                .processInstanceId(selectHistoryByIdBO.getInstanceId())
                .list();
        List<HashMap<String,Object>> historicActivityList = new ArrayList<>();
        for(HistoricActivityInstance historicActivityInstance:historicActivityInstanceList){
            if(historicActivityInstance.getActivityType().equals("userTask")){
                HashMap<String,Object> historicTask = new HashMap<>();
                String name = historicActivityInstance.getActivityName();
                historicTask.put("name",name);
                String assignee = historicActivityInstance.getAssignee();
                if(historicActivityInstance.getTaskId()!=null){
                    List<Comment> commentList = taskService.getTaskComments(historicActivityInstance.getTaskId());
                    if(commentList != null && !commentList.isEmpty()) {
                        String endTime = DateUtil.format(historicActivityInstance.getEndTime(),"yyyy年MM月dd日 HH:mm:ss");
                        historicTask.put("message",assignee+" 审批于"+endTime + "，批复意见："+commentList.get(0).getFullMessage());
                    }else{
                        historicTask.put("message",assignee+" 待审批");
                    }
                }
                historicActivityList.add(historicTask);
            }else if(historicActivityInstance.getActivityType().equals("startEvent")){
                HashMap<String,Object> historicTask = new HashMap<>();
                String startUser = historyService.createHistoricProcessInstanceQuery().processInstanceId(historicActivityInstance.getProcessInstanceId()).singleResult().getStartUserId();//获取发起人
                String name = historicActivityInstance.getActivityName();
                historicTask.put("name",name);
                historicTask.put("message",startUser+" 提交于"+DateUtil.format(historicActivityInstance.getEndTime(),"yyyy年MM月dd日 HH:mm:ss"));
                historicActivityList.add(historicTask);
            }else if(historicActivityInstance.getActivityType().equals("endEvent")) {
                HashMap<String, Object> historicTask = new HashMap<>();
                String name = historicActivityInstance.getActivityName();
                historicTask.put("name", name);
                historicTask.put("message", "结束于"+DateUtil.format(historicActivityInstance.getEndTime(), "yyyy年MM月dd日 HH:mm:ss"));
                historicActivityList.add(historicTask);
            }
        }
        Map<String,Object> result = new HashMap<>();
        result.put("list",historicActivityList);
        return JSONResult.ok(result);
    }

    @PostMapping("/getHighLightedActivities")
    @ApiOperation(value = "按实例ID查询流程活跃节点",notes = "按实例ID查询流程活跃节点", httpMethod = "POST")
    @PreFuncAuth("PROCESS:INSTANCE:SELECT")
    public JSONResult getHighLightedActivities(@Valid @RequestBody SelectHighLightActivitiesBO selectHighLightActivitiesBO){
        //获取流程实例 历史节点（已完成）
        List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(selectHighLightActivitiesBO.getInstanceId())
                .finished()
                .list();
        //高亮节点ID
        List<String> highPointList = new ArrayList<>();
        listFinished.forEach(s -> highPointList.add(s.getActivityId()));
        //获取流程实例 历史节点（待办节点）
        List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(selectHighLightActivitiesBO.getInstanceId())
                .unfinished()
                .list();
        //待办高亮节点
        Set<String> waitingToDoList = new HashSet<>();
        listUnFinished.forEach(s -> waitingToDoList.add(s.getActivityId()));
        BpmnModel bpmnModel = repositoryService.getBpmnModel(selectHighLightActivitiesBO.getDefinitionId());
        //创建转换对象
        BpmnXMLConverter converter = new BpmnXMLConverter();
        //把bpmnModel对象转换成字符
        byte[] bytes = converter.convertToXML(bpmnModel);
        String bpmnTemplate = new String(bytes);
        Map<String,Object> result = new HashMap<>();
        result.put("bpmnTemplate",bpmnTemplate);
        result.put("highPointList",highPointList);
        result.put("waitingToDoList",waitingToDoList);
        return JSONResult.ok(result);
    }

    @GetMapping(value ="/selectApprovalBpmn", produces ="image/svg+xml")
    @ApiOperation(value = "按实例ID查询流程跟踪",notes = "按实例ID查询流程跟踪", httpMethod = "GET")
    public String getProcessDiagram(@RequestParam("instanceId") String instanceId){
        // 获取流程引擎配置
        ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(instanceId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        List<String> highLightedActivities = runtimeService.getActiveActivityIds(instanceId);
        // 获取高亮显示的连线集合
        List<String> flows = new ArrayList<>();
        try{
            ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
            InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel,
                    "png", highLightedActivities, flows, engConf.getActivityFontName(),
                    engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(),
                    1.0, true);
            byte[] ByteArrayBuff = IOUtils.toByteArray(inputStream);
            return new String(ByteArrayBuff,StandardCharsets.UTF_8);
        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }

}
